package com.lxk.mall.pms.mapper;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lxk.mall.pms.controller.app.vo.AppProductSpuPageReqVO;
import com.lxk.mall.pms.domain.PmsProductSpu;
import com.lxk.mall.pms.domain.vo.spu.PmsProductSpuVo;
import com.lxk.mall.pms.enums.ProductConstants;
import com.lxk.mall.pms.enums.ProductSpuStatusEnum;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.common.mybatis.core.page.PageQuery;

import java.util.Objects;
import java.util.Set;

/**
 * 商品spuMapper接口
 *
 * @author Lion Li
 * @date 2024-06-06
 */
public interface PmsProductSpuMapper extends BaseMapperPlus<PmsProductSpu, PmsProductSpuVo> {
    default Long selectCount(String productType) {
        LambdaQueryWrapper<PmsProductSpu> queryWrapper = new LambdaQueryWrapper<>();
        // 库存小于等于警戒库存
        queryWrapper
            .eq(StrUtil.isNotBlank(productType), PmsProductSpu::getProductType, productType)
            .gt(PmsProductSpu::getStock, 0)
            .le(PmsProductSpu::getStock, ProductConstants.ALERT_STOCK)
            // 如果库存触发警戒库存且状态为回收站的话则不计入触发警戒库存的个数
            .notIn(PmsProductSpu::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus());
        return selectCount(queryWrapper);
    }

    /**
     * 获得商品 SPU 分页，提供给用户 App 使用
     */
    default Page<PmsProductSpu> selectPage(AppProductSpuPageReqVO pageReqVO, Set<Long> categoryIds) {
        LambdaQueryWrapper<PmsProductSpu> query = new LambdaQueryWrapper<>();
        // 关键字匹配，目前只匹配商品名
        if (StrUtil.isNotBlank(pageReqVO.getKeyword())) {
            query.like(PmsProductSpu::getCategoryId, pageReqVO.getKeyword());
        }
        // 分类
        if (CollUtil.isNotEmpty(categoryIds)) {
            query.in(PmsProductSpu::getCategoryId, categoryIds);
        }
        // 上架状态 且有库存
        query.eq(PmsProductSpu::getStatus, ProductSpuStatusEnum.ENABLE.getStatus());

        // 排序逻辑
        if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) {
            query.last(String.format(" ORDER BY (sales_count + virtual_sales_count) %s, sort DESC, id DESC",
                pageReqVO.getSortAsc() ? "ASC" : "DESC"));
        } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) {
            query.orderBy(true, pageReqVO.getSortAsc(), PmsProductSpu::getPrice)
                .orderByDesc(PmsProductSpu::getSort).orderByDesc(PmsProductSpu::getId);
        } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_CREATE_TIME)) {
            query.orderBy(true, pageReqVO.getSortAsc(), PmsProductSpu::getCreateTime)
                .orderByDesc(PmsProductSpu::getSort).orderByDesc(PmsProductSpu::getId);
        } else {
            query.orderByDesc(PmsProductSpu::getSort).orderByDesc(PmsProductSpu::getId);
        }
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(pageReqVO.getPageNo());
        pageQuery.setPageSize(pageReqVO.getPageSize());
        Page<PmsProductSpu> pmsProductSpuPage = selectPage(pageQuery.build(), query);
        return pmsProductSpuPage;
    }

    /**
     * 更新商品 SPU 浏览量
     *
     * @param id        商品 SPU 编号
     * @param incrCount 增加的数量
     */
    default void updateBrowseCount(Long id, int incrCount) {
        LambdaUpdateWrapper<PmsProductSpu> updateWrapper = new LambdaUpdateWrapper<PmsProductSpu>()
            .setSql(" browse_count = browse_count +" + incrCount)
            .eq(PmsProductSpu::getId, id);
        update(null, updateWrapper);
    }

    /**
     * 更新商品 SPU 库存
     *
     * @param id        商品 SPU 编号
     * @param incrCount 增加的库存数量
     */
    default int updateStock(Long id, Integer incrCount) {
        LambdaUpdateWrapper<PmsProductSpu> updateWrapper = new LambdaUpdateWrapper<PmsProductSpu>()
            // 负数，所以使用 + 号
            .setSql(" stock = stock +" + incrCount)
            .eq(PmsProductSpu::getId, id);
        return update(null, updateWrapper);
    }

    /**
     * 更新 SPU 库存（增加）
     *
     * @param id        编号
     * @param incrCount 增加库存（正数）
     */
    default void addStockIncr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSpu> lambdaUpdateWrapper = new LambdaUpdateWrapper<PmsProductSpu>()
            .setSql(" stock = stock + " + incrCount)
            .eq(PmsProductSpu::getId, id);
        update(null, lambdaUpdateWrapper);
    }

    /**
     * 更新 SPU 回滚预扣库存接口
     *
     * @param id        编号
     * @param incrCount 增加库存（正数）
     */
    default int addStockForeIncr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSpu> lambdaUpdateWrapper = new LambdaUpdateWrapper<PmsProductSpu>()
            .setSql(" stock = stock + " + incrCount)
            .setSql(" stock_fore = stock_fore - " + incrCount)
            .eq(PmsProductSpu::getId, id)
            .ge(PmsProductSpu::getStockFore, incrCount);
        return update(null, lambdaUpdateWrapper);
    }

    /**
     * 更新 SPU 库存（减少）
     *
     * @param id        编号
     * @param incrCount 增加库存（正数）
     */
    default int cutStockDecr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSpu> updateWrapper = new LambdaUpdateWrapper<PmsProductSpu>()
            .setSql(" stock = stock - " + incrCount) // 负数，所以使用 + 号
            .eq(PmsProductSpu::getId, id)
            .ge(PmsProductSpu::getStock, incrCount); // cas 逻辑
        return update(null, updateWrapper);
    }

    /**
     * 更新 SPU 预扣库存接口
     *
     * @param id        编号
     * @param incrCount 增加库存（正数）
     */
    default int cutStockForeDecr(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSpu> updateWrapper = new LambdaUpdateWrapper<PmsProductSpu>()
            .setSql(" stock = stock - " + incrCount)
            .setSql(" stock_fore = stock_fore + " + incrCount)
            .eq(PmsProductSpu::getId, id)
            .ge(PmsProductSpu::getStock, -incrCount); // cas 逻辑
        return update(null, updateWrapper);
    }

    /**
     * 减少stock_fore
     *
     * @param id
     * @param incrCount
     * @return
     */
    default int actCutStockFore(Long id, Integer incrCount) {
        Assert.isTrue(incrCount > 0);
        LambdaUpdateWrapper<PmsProductSpu> updateWrapper = new LambdaUpdateWrapper<PmsProductSpu>()
            .setSql(" stock_fore = stock_fore - " + incrCount)
            .eq(PmsProductSpu::getId, id)
            .ge(PmsProductSpu::getStockFore, incrCount); // cas 逻辑
        return update(null, updateWrapper);
    }

}
